package com.ddw.meedeeuh.views;

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.BorderFactory;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.JToolBar;
import javax.swing.ListModel;
import javax.swing.SwingUtilities;
import javax.swing.border.CompoundBorder;

import com.ddw.meedeeuh.presenters.MoviesPresenter.ListModelMovie;
import com.ddw.meedeeuh.presenters.MoviesPresenter.MoviesView;

@SuppressWarnings("serial")
public class MoviesViewImpl extends JPanel implements MoviesView {

	private final JList<ListModelMovie> list = new JList<ListModelMovie>();
	private final JButton searchButton = new JButton("Search");
	private final JTextField searchText = new JTextField();
	private final JButton buttonRefresh = new JButton("Refresh");
	private final JButton buttonImport = new JButton("Import");
	private final JButton buttonScrape = new JButton("Scrape");

	public MoviesViewImpl() {
		super(new GridBagLayout());

		addToolbar();
		addSearchTextBox();
		addSearchButton();
		addMoviesList();
	}

	private void addToolbar() {
		final JToolBar toolbar = new JToolBar(JToolBar.HORIZONTAL);
		toolbar.setFloatable(false);
		toolbar.setRollover(true);
		toolbar.setMargin(new Insets(5, 5, 5, 5));

		// Setup toolbar buttons
		this.buttonRefresh.setToolTipText("Refreshes your movies list from your local database");
		this.buttonImport.setToolTipText("Imports movies from the filesystem into your local database");
		this.buttonScrape.setToolTipText("Scrapes information for your movies from external sources into your local database");

		// Add toolbar buttons
		toolbar.add(this.buttonRefresh);
		toolbar.add(this.buttonImport);
		toolbar.add(this.buttonScrape);

		final GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.weightx = 1.0;
		gbc.gridx = gbc.gridy = 0;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.gridwidth = 2;
		gbc.insets = new Insets(0, 0, 0, 0);
		add(toolbar, gbc);
	}

	private void addMoviesList() {
		// Setup cell renderer
		this.list.setCellRenderer(new DefaultListCellRenderer() {

			@Override
			public Component getListCellRendererComponent(JList<?> list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
				final JLabel label = (JLabel) super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
				label.setBorder(BorderFactory.createEmptyBorder(2, 5, 2, 5));
				return label;
			}

		});

		final GridBagConstraints gbc = new GridBagConstraints();
		gbc.weightx = gbc.weighty = 1.0;
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.gridx = 0;
		gbc.gridy = 2;
		gbc.gridwidth = GridBagConstraints.REMAINDER;
		gbc.insets = new Insets(0, 5, 5, 5);
		add(new JScrollPane(this.list), gbc);
	}

	private void addSearchButton() {
		final GridBagConstraints gbc = new GridBagConstraints();
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.gridx = 1;
		gbc.gridy = 1;
		gbc.insets = new Insets(5, 0, 5, 5);

		// Setup search button area
		add(this.searchButton, gbc);
	}

	private void addSearchTextBox() {
		final GridBagConstraints gbc = new GridBagConstraints();
		gbc.weightx = 1.0;
		gbc.anchor = GridBagConstraints.CENTER;
		gbc.fill = GridBagConstraints.HORIZONTAL;
		gbc.gridx = 0;
		gbc.gridy = 1;
		gbc.ipadx = gbc.ipady = 7;
		gbc.insets = new Insets(5, 5, 5, 0);

		// Setup border to indent text
		this.searchText.setBorder(new CompoundBorder(BorderFactory.createEtchedBorder(),
				BorderFactory.createEmptyBorder(0, 5, 0, 5)));

		// Setup search text area
		add(this.searchText, gbc);
	}

	@Override
	public Component asComponent() {
		return this;
	}

	@Override
	public void setListModel(ListModel<ListModelMovie> model) {
		this.list.setModel(model);
	}

	@Override
	public void addSearchListener(ActionListener listener) {
		this.searchButton.addActionListener(listener);
	}

	@Override
	public String getSearchText() {
		return this.searchText.getText();
	}

	@Override
	public void setSearchMessage(String message) {
		JOptionPane.showMessageDialog(SwingUtilities.getRoot(this),
				message, "Search", JOptionPane.INFORMATION_MESSAGE);
	}

	@Override
	public void addRefreshListener(ActionListener listener) {
		this.buttonRefresh.addActionListener(listener);
	}

	@Override
	public void clearSearchText() {
		this.searchText.setText(null);
	}

	@Override
	public void addScrapeListener(ActionListener listener) {
		this.buttonScrape.addActionListener(listener);
	}

	@Override
	public void addImportListener(ActionListener listener) {
		this.buttonImport.addActionListener(listener);
	}

	@Override
	public boolean validateScrape() {
		return JOptionPane.showConfirmDialog(SwingUtilities.getRoot(this),
				"Are you sure you want to start a movie scrape?\nThis can take some time.",
				"Scrape", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
	}

	@Override
	public boolean validateImport() {
		return JOptionPane.showConfirmDialog(SwingUtilities.getRoot(this),
				"Are you sure you want to start a movie import?\nThis will clear your local database and attempt to re-import all movies.\nThis can take some time.",
				"Scrape", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE) == JOptionPane.YES_OPTION;
	}

	@Override
	public void addMovieSelectionListener(final ActionListener listener) {
		this.list.addMouseListener(new MouseAdapter() {

			@Override
			public void mouseClicked(MouseEvent e) {
				if(e.getClickCount() == 2) {
					final int index = list.getSelectedIndex();
					if(index != -1) {
						listener.actionPerformed(new ActionEvent(list, ActionEvent.ACTION_PERFORMED, null));
					}
				}
			}

		});
		this.list.addKeyListener(new KeyAdapter() {

			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_SPACE) {
					final int index = list.getSelectedIndex();
					if(index != -1) {
						listener.actionPerformed(new ActionEvent(list, ActionEvent.ACTION_PERFORMED, null));
					}
				}
			}

		});
	}

	@Override
	public ListModelMovie getSelectedMovie() {
		return list.getSelectedValue();
	}

}
